package com.zzoranor.presentationserver;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Vector;

import protocols.ProtocolsProto.HelloWorld;
import protocols.ProtocolsProto.ServerToClientMessage;

import com.zzoranor.util.Log;

/**
 * This class is responsible for sending the messages 
 * received from the Dispatcher to a single client, provided
 * in the form of a ClientInfo object. 
 * @author Tim
 *
 */
public class ClientSender extends Thread {

	private Vector<String> messageQueue = new Vector<String>();
	
	private ClientInfo clientInfo;
	private ServerDispatcher serverDispatcher;
	private DataOutputStream out;
	
	public ClientSender(ClientInfo clientInfo, ServerDispatcher serverDispatcher) {
		this.clientInfo = clientInfo;
		this.serverDispatcher = serverDispatcher;
	}
	
	public void setup()
	{
		try {
			out = new DataOutputStream(clientInfo.getSocket().getOutputStream());
			
		} catch (IOException e) {
			Log.printStackTrace(e);
		}
	}
	
	public synchronized void sendMessage(String message) {
		messageQueue.add(message);
		notify();
		
	}
	
	private synchronized String getNextMessageFromQueue() throws InterruptedException
	{
		while(messageQueue.size() == 0)
		{
			wait();
		}
		String message = messageQueue.get(0);
		messageQueue.removeElementAt(0);
		return message;
	}
	
	private void sendMessageToClient(String message)
	{
		try {
			ServerToClientMessage msg = ServerToClientMessage.newBuilder()
					.setHelloWorld(
							HelloWorld
							.newBuilder()
							.setHelloWorld(message)
							.build()
							).build();
			byte size = (byte) msg.getSerializedSize();
			byte[] array = msg.toByteArray();
			out.writeByte(size);
			out.write(array);
		} catch (IOException e) {
			Log.printStackTrace(e);	
			closeOutputs();
		}
	}
	
	public void run()
	{
		try
		{
			while(!isInterrupted())
			{
				String message = getNextMessageFromQueue();
				sendMessageToClient(message);
			}
		}catch(Exception e)
		{
			Log.e("Exception caught: " + e);
			Log.printStackTrace(e);
		}
		
		clientInfo.getListener().interrupt();
		serverDispatcher.deleteClient(clientInfo);
	}
	
	public void closeOutputs()
	{
		try {
			if(out != null)
			{
				out.close();
			}
		} catch (IOException e) {
			
		}
		
	}

}
